Skip to content

Модуль похоти киборга#480

Draft
crestoedge wants to merge 20 commits intospace-sunrise:masterfrom
crestoedge:service-borg-lewd-module
Draft

Модуль похоти киборга#480
crestoedge wants to merge 20 commits intospace-sunrise:masterfrom
crestoedge:service-borg-lewd-module

Conversation

@crestoedge
Copy link
Contributor

@crestoedge crestoedge commented Feb 21, 2026

Кратное описание

Модуль похоти киборга.
Система, которая позволяет присвоить компонент панельки при вставке модуля - в ПРе. Она на стороне сервера, так как ебучие предикшены ивента клиентом полностью её ломают. Если это как-то можно исправить - помогите. (з.ы. в аргументах ивента isHandled или isPredicted тупо нет)

По какой причине

Забавный ЕРП гиммик (дает возможность боргам юзать панельку, игрушки в комплекте)

Медиа(Видео/Скриншоты)

2026-2-21_04 02 16

Changelog

🆑 Miolo

  • add: Добавлен модуль похоти киборга.

Summary by CodeRabbit

Релиз-ноты

  • Новые функции

    • Добавлен "Модуль похоти" для боргов — устанавливается, даёт встроенные предметы, действия и дополнительную руку; доступен в исследованиях и на лathe.
    • Добавлена категория ERPToy и множество новых игрушек/товаров.
    • Новые иконки/состояния модуля и синий эффект ночного видения.
    • Добавлен гипоспрей для борга с новыми режимами.
  • Исправления

    • Панель взаимодействий теперь корректно закрывается при удалении компонента; глаголы не создаются без компонента.
  • Локализация

    • Добавлены строки en-US и ru-RU для модуля, инструмента и исследования.

add: locstrings and credits, module as default for service cyborg
tweak: renaming
remove: testing items from innate module component
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 21, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Добавлена система BorgModuleInnateSystem и сопутствующие события/компоненты и прототипы для нового модуля BorgModuleLustful: при установке модуль создаёт предметы и действия, добавляет компоненты к шасси; при снятии — удаляет действия, предметы и добавленные компоненты. Также добавлены локализации, рецепты, теги и спрайты.

Changes

Cohort / File(s) Summary
Система врождённых модулей
Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs, Content.Server/_Lust/Borgs/BorgModuleInnateComponent.cs
Новая система и компонент: подписка на установку/снятие, создание контейнера innate-предметов, добавление/удаление Innate-компонентов, создание/удаление действий; хранение списков InnateItems и Actions.
События действий модуля
Content.Shared/_Lust/Borgs/BorgModuleInnateEvents.cs
Добавлены события ModuleInnateUseItem и ModuleInnateInteractionItem для передачи EntityUid предмета в обработчики действий.
Действия (прототипы)
Resources/Prototypes/_Sunrise/Actions/innate_actions.yml
Добавлены прототипы действий ModuleInnateUseItemAction и ModuleInnateInteractionItemAction (Instant и Target/EntityTarget).
Прототип модуля "Lustful"
Resources/Prototypes/_Lust/Entities/Objects/Specific/Robotics/borg_modules.yml
Новый прототип BorgModuleLustful с наборами рук, Innate-компонентом (Interactions, ErpStatus), HypoBorgLustful и BorgModuleIcon.
ERP игрушки — реорганизация
Resources/Prototypes/_Lust/Entities/ERP/Toys/toys.yml
Введён общий родитель ERPToy и обновлена иерархия/теги для множества игрушек (родитель/теги изменены).
Теги, рецепты, исследование и сборка
Resources/Prototypes/_Lust/tags.yml, Resources/Prototypes/Recipes/Lathes/Packs/robotics.yml, Resources/Prototypes/_Lust/Recipes/Lathes/robot_modules.yml, Resources/Prototypes/_Lust/Research/civilianservices.yml, Resources/Prototypes/borg_types.yml
Добавлен тег ERPToy; добавлен рецепт BorgModuleLustful, запись в recipePack и технология LustfulCyborgModules; модуль добавлен в defaultModules для Service борга.
Инструменты и инжекторы (гипоспрей)
Resources/Prototypes/_Lust/Entities/Objects/Specific/Robotics/borg_tools.yml, Resources/Textures/Objects/Specific/Medical/hypospray.rsi/meta.json
Добавлен прототип HypoBorgLustful с режимами инжектора и новое состояние спрайта borghypolustful.
Локализации
Resources/Locale/en-US/_prototypes/_lust/.../borg_modules.ftl, Resources/Locale/ru-RU/_prototypes/_lust/.../borg_modules.ftl, Resources/Locale/en-US/_strings/_lust/.../technologies.ftl, Resources/Locale/ru-RU/_strings/_lust/.../technologies.ftl, Resources/Locale/.../borg_tools.ftl
Добавлены строки локализации для модуля, инструмента и технологии на en-US и ru-RU.
Спрайты и оверлеи
Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json, Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/meta.json, Resources/Prototypes/_Sunrise/Entities/Effects/overlays.yml
Добавлены состояния спрайтов lustful и icon-lustful, обновлена атрибуция, добавлен overlay EffectNightVisionBlue.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant EntitySys as EntitySystem
    participant ModuleSys as BorgModuleInnateSystem
    participant ActionSys as ActionSystem
    participant InteractionSys as InteractionSystem
    participant Borg as BorgChassis

    User->>EntitySys: Устанавливает BorgModuleLustful
    EntitySys->>ModuleSys: ComponentAdd(BorgModuleInnateComponent)
    ModuleSys->>Borg: Создаёт контейнер InnateItems и добавляет InnateComponents
    ModuleSys->>ActionSys: Создаёт действия (use/interaction) и привязывает к шасси
    ModuleSys->>ModuleSys: Сохраняет IDs InnateItems и Actions

    Borg->>ActionSys: Активирует действие (use/target)
    ActionSys->>ModuleSys: Генерирует ModuleInnateUseItem / ModuleInnateInteractionItem
    ModuleSys->>InteractionSys: Вызывает UseInHandEvent или запускает целевое взаимодействие
    InteractionSys->>Borg: Выполняет взаимодействие с предметом

    User->>EntitySys: Снимает модуль
    EntitySys->>ModuleSys: ComponentRemove(BorgModuleInnateComponent)
    ModuleSys->>ActionSys: Удаляет действия
    ModuleSys->>Borg: Удаляет InnateItems и InnateComponents
Loading

Estimated code review effort

🎯 3 (Умеренная) | ⏱️ ~25 минут

Poem

🐰 Я — кролик, код шепчу в ночи,
Модуль в шасси встал — и зажглись лучи.
Предмет, действие, спрайт и рецепт,
Пусть борг весело танцует при свет!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Заголовок на русском языке полностью соответствует основному изменению PR — добавлению модуля похоти киборга. Он ясный, конкретный и точно описывает главное нововведение.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 21, 2026

RSI Diff Bot; head commit dffd74e merging into afd03bf
This PR makes changes to 1 or more RSIs. Here is a summary of all changes:

Resources/Textures/Interface/Actions/actions_borg.rsi

State Old New Status
lustful-module Added

Resources/Textures/Objects/Specific/Medical/hypospray.rsi

State Old New Status
borghypolustful Added

Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi

State Old New Status
icon-lustful Added
lustful Added

Edit: diff updated after dffd74e

@crestoedge crestoedge force-pushed the service-borg-lewd-module branch from e4eea43 to 37d5151 Compare February 21, 2026 00:52
@crestoedge crestoedge marked this pull request as ready for review February 21, 2026 01:04
@crestoedge
Copy link
Contributor Author

Стоит добавить:

  1. Рецепт крафта
  2. Ещё больше гиммиков?

@crestoedge
Copy link
Contributor Author

220 лейблов 😨

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Resources/Prototypes/borg_types.yml (1)

315-322: ⚠️ Potential issue | 🔴 Critical

Модулю BorgModuleLustful недостаёт правильного родительского класса и компонента Tag для совместимости с системой установки модулей

Модуль определён с неверным родителем [ BaseBorgModule, BaseProviderBorgModule ] вместо [ BaseBorgModuleService, BaseProviderBorgModule ], как у всех остальных сервис-модулей (BorgModulePen, BorgModuleMusique, BorgModuleGardening и т.д.). Кроме того, ему недостаёт компонента Tag с тегом BorgModuleService и компонента BorgModule с borgFitTypes, которые определяют совместимость модуля с системой слотов. В текущем состоянии модуль будет работать только как предустановленный модуль в defaultModules, но не сможет быть переустановлен вручную через систему модулей борга.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Resources/Prototypes/borg_types.yml` around lines 315 - 322, Модуль
BorgModuleLustful объявлен с неверными родительскими классами и без необходимых
компонентов для совместимости со системой модулей; замените его родителей на
BaseBorgModuleService и BaseProviderBorgModule (как в
BorgModulePen/BorgModuleMusique/BorgModuleGardening), добавьте компонент Tag с
tag: "BorgModuleService" и компонент BorgModule с корректным полем borgFitTypes
(соответствующим другим сервис-модулям) чтобы модуль мог
устанавливаться/сниматься через систему слотов.
Resources/Prototypes/_Lust/Entities/ERP/Toys/toys.yml (1)

416-436: ⚠️ Potential issue | 🟡 Minor

ToyHandcuffs потеряет тег ERPToy из-за переопределения компонента Tag.

Родитель ERPToy определяет Tag с ERPToy. Но ToyHandcuffs определяет свой компонент Tag (строки 434-436) только с Handcuffs, что переопределит родительский список тегов. В результате ToyHandcuffs не будет иметь тега ERPToy, что противоречит цели рефакторинга. Ср. ERPShibariRope (строки 179-182), где оба тега указаны явно.

Предлагаемое исправление
   - type: Tag
     tags:
     - Handcuffs
+    - ERPToy
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Resources/Prototypes/_Lust/Entities/ERP/Toys/toys.yml` around lines 416 -
436, Компонент Tag в сущности ToyHandcuffs переопределяет родительский Tag из
ERPToy и удаляет тег ERPToy; исправьте это, указав оба тега в компоненте Tag для
ToyHandcuffs (включая ERPToy и Handcuffs) или удалив компонент Tag в
ToyHandcuffs чтобы унаследовать родительский Tag; найдите сущности ToyHandcuffs,
ERPToy и пример ERPShibariRope и примените аналогичное решение (добавьте ERPToy
рядом с Handcuffs или уберите локальный Tag).
🧹 Nitpick comments (2)
Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs (2)

183-204: Проверьте обработку случая, когда args.Item — невалидный EntityUid.

Если по какой-либо причине предмет был удалён (например, при конфликте с другим модулем, см. выше), RaiseLocalEvent на невалидном EntityUid и Transform(args.Target) могут привести к исключению. Рекомендуется добавить проверку существования сущности.

Пример защитной проверки
 private void OnInnateUseItem(Entity<BorgModuleInnateComponent> ent, ref ModuleInnateUseItem args)
 {
+    if (!Exists(args.Item))
+        return;
+
     var ev = new UseInHandEvent(args.Performer);
     RaiseLocalEvent(args.Item, ev);
     args.Handled = true;
 }

 private void OnInnateInteractionItem(Entity<BorgModuleInnateComponent> ent, ref ModuleInnateInteractionItem args)
 {
+    if (!Exists(args.Item) || !Exists(args.Target))
+        return;
+
     _interactions.InteractUsing(
         args.Performer,
         args.Item,
         args.Target,
         Transform(args.Target).Coordinates,
         false,
         false,
         false);
     args.Handled = true;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs` around lines 183 - 204,
The handlers OnInnateUseItem and OnInnateInteractionItem must guard against
deleted/invalid entities: before calling RaiseLocalEvent(args.Item, ...) or
Transform(args.Target) / _interactions.InteractUsing(...), check that args.Item
and args.Target exist (e.g., EntityManager.Exists/IsValidEntity or the project's
equivalent) and skip the call (or return) if not; only set args.Handled = true
after confirming the entity existed and the operation was invoked to avoid
null/invalid-UID exceptions in ModuleInnateUseItem and
ModuleInnateInteractionItem.

45-56: Избыточная проверка после EnsureContainer.

TryGetContainer на строке 52 всегда вернёт true, так как контейнер только что был создан/подтверждён на строке 48. Проверку можно упростить.

Упрощение
 private void OnInstalled(Entity<BorgModuleInnateComponent> module, ref BorgModuleInstalledEvent args)
 {
     var containerManager = EnsureComp<ContainerManagerComponent>(args.ChassisEnt);
-    _containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId, containerManager);
+    var container = _containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId, containerManager);

     EntityManager.AddComponents(args.ChassisEnt, module.Comp.InnateComponents);

-    if (!_containers.TryGetContainer(args.ChassisEnt, InnateItemsContainerId, out var container))
-        return;
-
     AddItems(args.ChassisEnt, module, container);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs` around lines 45 - 56,
In OnInstalled remove the redundant existence check after calling
_containers.EnsureContainer: since EnsureContainer just created/ensured the
InnateItemsContainerId, retrieve the container and call AddItems directly (e.g.
replace the if-check using TryGetContainer with a direct retrieval—either
_containers.GetContainer<Container>(args.ChassisEnt, InnateItemsContainerId) if
available, or call _containers.TryGetContainer(args.ChassisEnt,
InnateItemsContainerId, out var container) without an early return) and then
invoke AddItems(args.ChassisEnt, module, container); keep references to
OnInstalled, _containers, InnateItemsContainerId, and AddItems to locate the
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs`:
- Around line 13-14: В XML-комментарии над системой выдачи предметов исправьте
опечатку: в комментарии для класса/файла BorgModuleInnateSystem замените слово
"космпонентов" на корректное "компонентов" (отредактируйте строку внутри
тройного слеша /// <summary> ... </summary> соответствующего комментария).
- Around line 61-72: OnUninstalled currently cleans a shared container
(InnateItemsContainerId) which can delete items belonging to other modules;
change the design so each BorgModuleInnateComponent tracks its own created item
entities (e.g., add a CreatedItems list on BorgModuleInnateComponent similar to
Actions) and only delete those entities on uninstall. Update CreateInnateItem to
add the spawned item entity to module.Comp.CreatedItems (and still put it in the
chassis container if needed), and update OnUninstalled to iterate
module.Comp.CreatedItems to delete/cleanup just those entities, then clear
module.Comp.CreatedItems and module.Comp.Actions and remove components as
before; ensure UseItems/InteractionItems handling is updated to reference the
module’s own CreatedItems when necessary.

In `@Content.Server/_Sunrise/InteractionsPanel/InteractionsPanel.Interactions.cs`:
- Line 46: The handler OnInteractionsComponentRemove registered via
SubscribeLocalEvent for InteractionsComponent currently does nothing (its only
action _ui.RemoveUi is commented out) and should be fixed: either remove the
SubscribeLocalEvent registration and the OnInteractionsComponentRemove method
entirely to avoid the no-op subscription, or implement a safe UI cleanup inside
OnInteractionsComponentRemove that checks entity/state before calling
_ui.RemoveUi (handle nulls/already-deleted entities and catch/log exceptions) so
removal won’t crash during ComponentRemove; update or remove the offending
comment as well.

In `@Content.Shared/_Lust/Borgs/BorgModuleInnateEvents.cs`:
- Around line 19-21: Fix the typo in the XML <summary> comment in
Content.Shared/_Lust/Borgs/BorgModuleInnateEvents.cs: change "Ивент на активацию
встроенного предмета с взаимдоействием с целью" to use the correct Russian word
"взаимодействием" so the summary reads "Ивент на активацию встроенного предмета
с взаимодействием с целью".

---

Outside diff comments:
In `@Resources/Prototypes/_Lust/Entities/ERP/Toys/toys.yml`:
- Around line 416-436: Компонент Tag в сущности ToyHandcuffs переопределяет
родительский Tag из ERPToy и удаляет тег ERPToy; исправьте это, указав оба тега
в компоненте Tag для ToyHandcuffs (включая ERPToy и Handcuffs) или удалив
компонент Tag в ToyHandcuffs чтобы унаследовать родительский Tag; найдите
сущности ToyHandcuffs, ERPToy и пример ERPShibariRope и примените аналогичное
решение (добавьте ERPToy рядом с Handcuffs или уберите локальный Tag).

In `@Resources/Prototypes/borg_types.yml`:
- Around line 315-322: Модуль BorgModuleLustful объявлен с неверными
родительскими классами и без необходимых компонентов для совместимости со
системой модулей; замените его родителей на BaseBorgModuleService и
BaseProviderBorgModule (как в
BorgModulePen/BorgModuleMusique/BorgModuleGardening), добавьте компонент Tag с
tag: "BorgModuleService" и компонент BorgModule с корректным полем borgFitTypes
(соответствующим другим сервис-модулям) чтобы модуль мог
устанавливаться/сниматься через систему слотов.

---

Nitpick comments:
In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs`:
- Around line 183-204: The handlers OnInnateUseItem and OnInnateInteractionItem
must guard against deleted/invalid entities: before calling
RaiseLocalEvent(args.Item, ...) or Transform(args.Target) /
_interactions.InteractUsing(...), check that args.Item and args.Target exist
(e.g., EntityManager.Exists/IsValidEntity or the project's equivalent) and skip
the call (or return) if not; only set args.Handled = true after confirming the
entity existed and the operation was invoked to avoid null/invalid-UID
exceptions in ModuleInnateUseItem and ModuleInnateInteractionItem.
- Around line 45-56: In OnInstalled remove the redundant existence check after
calling _containers.EnsureContainer: since EnsureContainer just created/ensured
the InnateItemsContainerId, retrieve the container and call AddItems directly
(e.g. replace the if-check using TryGetContainer with a direct retrieval—either
_containers.GetContainer<Container>(args.ChassisEnt, InnateItemsContainerId) if
available, or call _containers.TryGetContainer(args.ChassisEnt,
InnateItemsContainerId, out var container) without an early return) and then
invoke AddItems(args.ChassisEnt, module, container); keep references to
OnInstalled, _containers, InnateItemsContainerId, and AddItems to locate the
change.

Comment on lines +61 to +72
private void OnUninstalled(Entity<BorgModuleInnateComponent> module, ref BorgModuleUninstalledEvent args)
{
foreach (var action in module.Comp.Actions)
_actions.RemoveAction(args.ChassisEnt, action);

if (_containers.TryGetContainer(args.ChassisEnt, InnateItemsContainerId, out var container))
_containers.CleanContainer(container);

module.Comp.Actions.Clear();

EntityManager.RemoveComponents(args.ChassisEnt, module.Comp.InnateComponents);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я решил данную проблему. Но подобная проблема может случится и с компонентами - что если компонент из списка уже есть у сущности?
Как я могу отслеживать уже установленные компоненты?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@crestoedge, отличный вопрос! Действительно, с компонентами может возникнуть та же проблема — если компонент уже существует на шасси (от другого модуля или изначально), то при деинсталляции вы удалите чужой компонент.

Для отслеживания установленных компонентов можно использовать аналогичный подход — хранить ComponentRegistry с фактически добавленными компонентами:

1. Добавьте поле в BorgModuleInnateComponent:

[DataField, AutoNetworkedField]
public ComponentRegistry AddedComponents = new();

2. Обновите OnInstalled — проверяйте наличие перед добавлением:

private void OnInstalled(Entity<BorgModuleInnateComponent> module, ref BorgModuleInstalledEvent args)
{
    var containerManager = EnsureComp<ContainerManagerComponent>(args.ChassisEnt);
    _containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId, containerManager);

    // Фильтруем компоненты - добавляем только те, которых еще нет
    var componentsToAdd = new ComponentRegistry();
    foreach (var (name, component) in module.Comp.InnateComponents)
    {
        var compType = component.Component.GetType();
        if (!EntityManager.HasComponent(args.ChassisEnt, compType))
        {
            componentsToAdd.Add(name, component);
        }
    }

    EntityManager.AddComponents(args.ChassisEnt, componentsToAdd);
    module.Comp.AddedComponents = componentsToAdd; // Сохраняем что добавили

    if (!_containers.TryGetContainer(args.ChassisEnt, InnateItemsContainerId, out var container))
        return;

    AddItems(args.ChassisEnt, module, container);
}

3. Обновите OnUninstalled — удаляйте только отслеживаемые компоненты:

private void OnUninstalled(Entity<BorgModuleInnateComponent> module, ref BorgModuleUninstalledEvent args)
{
    foreach (var action in module.Comp.Actions)
        _actions.RemoveAction(args.ChassisEnt, action);

    foreach (var item in module.Comp.CreatedItems)
        QueueDel(item);

    module.Comp.Actions.Clear();
    module.Comp.CreatedItems.Clear();

    // Удаляем только те компоненты, которые этот модуль добавил
    EntityManager.RemoveComponents(args.ChassisEnt, module.Comp.AddedComponents);
    module.Comp.AddedComponents.Clear();
}

Этот подход гарантирует, что:

  • ✅ Не перезаписываются существующие компоненты
  • ✅ Каждый модуль отслеживает только свои компоненты
  • ✅ При деинсталляции удаляются только компоненты, добавленные этим модулем
  • ✅ Несколько модулей могут безопасно работать одновременно

Альтернативный вариант — использовать счетчик ссылок для каждого компонента, но для вашего случая это избыточно.


🧠 Learnings used
Learnt from: Kendrick15
Repo: space-sunrise/lust-station PR: 301
File: Resources/Locale/ru-RU/_strings/_lust/flavors/flavor-profiles.ftl:1-1
Timestamp: 2025-07-08T21:33:23.476Z
Learning: Проект lust-station является взрослым контентом с ERP (Erotic Role Play) функциональностью, где активно используется ненормативная лексика в локализациях, включая акценты персонажей, комментарии разработчиков и игровой контент. Стиль локализации соответствует взрослой тематике проекта.

Learnt from: Esco-dev
Repo: space-sunrise/lust-station PR: 427
File: Resources/Prototypes/_Sunrise/Roles/Jobs/Command/nanotrasen_representative.yml:7-7
Timestamp: 2025-12-12T08:52:50.213Z
Learning: В проекте space-sunrise/lust-station используется комментарий "# Lust Edit" для маркировки изменений в файлах относительно upstream проекта sunrise-station. Эти комментарии являются частью системы документирования fork-специфичных изменений и не должны удаляться.

Learnt from: Esco-dev
Repo: space-sunrise/lust-station PR: 427
File: Resources/Prototypes/_Sunrise/Roles/Jobs/Command/nanotrasen_representative.yml:7-7
Timestamp: 2025-12-12T08:52:35.387Z
Learning: В проекте space-sunrise/lust-station используется комментарий "#Lust Edit" для маркировки изменений в файлах, специфичных для форка lust-station. Эти комментарии являются частью системы документирования изменений относительно upstream проекта sunrise-station и не должны удаляться.

Learnt from: Orvex07
Repo: space-sunrise/lust-station PR: 442
File: Resources/Prototypes/_Lust/CP/Weapons/hl2_weapons.yml:56-105
Timestamp: 2025-12-31T16:02:40.555Z
Learning: В проекте space-sunrise/lust-station при анализе PR с контентом в директории _Lust/CP необходимо проверять существование прототипов не только в файлах PR, но и в upstream директории _Sunrise, так как _Lust может использовать прототипы оружия, магазинов и других предметов из _Sunrise (например, MagazineMP7 определён в Resources/Prototypes/_Sunrise/Entities/Objects/Weapons/Guns/Ammunition/Magazines/pistol.yml).

Learnt from: darneya
Repo: space-sunrise/lust-station PR: 425
File: Resources/Prototypes/_Lust/CP/Clothing/jumpsuits.yml:197-208
Timestamp: 2025-12-27T09:48:52.949Z
Learning: В проекте space-sunrise/lust-station при добавлении контента Half-Life 2 (HL2) по техническому заданию пользователя Wein описания предметов должны строго следовать предоставленному ТЗ, даже если они могут показаться семантически несоответствующими названию предмета (например, ClothingUniformJumpsuitCPRefugee с описанием помощника на поле боя).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
Content.Server/_Sunrise/InteractionsPanel/InteractionsPanel.Interactions.cs (1)

579-583: Порядок проверок можно оптимизировать: InteractionsComponent следует проверять до UserInterfaceComponent

HasComp<InteractionsComponent>(args.User) (строка 582) — доменно более значимый и лёгкий guard для данной системы, чем TryComp<UserInterfaceComponent> (строка 579), который к тому же выполняет более дорогую операцию получения компонента. Переместив HasComp выше, мы быстро отсекаем пользователей без панели взаимодействий, прежде чем тратить ресурсы на TryComp.

♻️ Предлагаемое изменение
     private void AddInteractionsVerb(Entity<InteractionsComponent> ent, ref GetVerbsEvent<AlternativeVerb> args)
     {
+        if (!HasComp<InteractionsComponent>(args.User))
+            return;
+
         if (!TryComp<UserInterfaceComponent>(args.User, out var interfaceComponent))
             return;
-
-        if (!HasComp<InteractionsComponent>(args.User))
-            return;
-
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Server/_Sunrise/InteractionsPanel/InteractionsPanel.Interactions.cs`
around lines 579 - 583, Swap the guard checks so
HasComp<InteractionsComponent>(args.User) runs before
TryComp<UserInterfaceComponent>(args.User, out var interfaceComponent);
specifically, move the HasComp<InteractionsComponent> check above the
TryComp<UserInterfaceComponent> call to reject users without an
InteractionsComponent early and avoid the more expensive TryComp operation on
those users (keep returning immediately in both guards and preserve the same
variables/names: args.User, InteractionsComponent, UserInterfaceComponent,
interfaceComponent).
Resources/Prototypes/_Lust/Entities/ERP/Toys/toys.yml (1)

226-226: Незначительная непоследовательность: одноэлементный массив в parent.

Строки 226, 256, 369 и 389 используют форму parent: [ERPToy] (массив с одним элементом), тогда как строка 417 использует скалярную форму parent: ERPToy. Обе формы функционально идентичны; для единообразия предпочтительна скалярная форма для одиночного родителя.

♻️ Предлагаемое исправление
- parent: [ERPToy]
+ parent: ERPToy

(применить к строкам 226, 256, 369, 389)

Also applies to: 256-256, 369-369, 389-389

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Resources/Prototypes/_Lust/Entities/ERP/Toys/toys.yml` at line 226, The YAML
contains inconsistent parent notation: replace the array form parent: [ERPToy]
with the scalar form parent: ERPToy wherever the single-parent array is used
(i.e., change every occurrence of parent: [ERPToy] to parent: ERPToy) so it
matches the existing scalar usage; search for the key "parent" with the value
"[ERPToy]" and update those entries to "parent: ERPToy" to keep notation
consistent.
Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs (2)

47-55: EnsureContainer возвращает контейнер — используйте его напрямую.

Результат EnsureContainer выбрасывается, а следующий TryGetContainer (строка 52) всегда вернёт true сразу после него. return на строке 53 — недостижимый код.

♻️ Предлагаемое упрощение
-        var containerManager = EnsureComp<ContainerManagerComponent>(args.ChassisEnt);
-        _containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId, containerManager);
-
-        EntityManager.AddComponents(args.ChassisEnt, module.Comp.InnateComponents);
-
-        if (!_containers.TryGetContainer(args.ChassisEnt, InnateItemsContainerId, out var container))
-            return;
-
-        AddItems(args.ChassisEnt, module, container);
+        var containerManager = EnsureComp<ContainerManagerComponent>(args.ChassisEnt);
+        var container = _containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId, containerManager);
+
+        EntityManager.AddComponents(args.ChassisEnt, module.Comp.InnateComponents);
+
+        AddItems(args.ChassisEnt, module, container);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs` around lines 47 - 55,
The code calls _containers.EnsureContainer<Container>(args.ChassisEnt,
InnateItemsContainerId, containerManager) but ignores its return value and then
calls _containers.TryGetContainer(...) which is unnecessary and makes the
subsequent return unreachable; instead capture the container returned by
EnsureContainer (assign to a variable, e.g. var container =
_containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId,
containerManager)), remove the TryGetContainer branch and unreachable return,
and pass that container directly to AddItems(args.ChassisEnt, module,
container); keep a null check only if EnsureContainer can return null (otherwise
omit).

11-11: Несоответствие неймспейса пути файла.

Файл расположен в Content.Server/_Lust/Borgs/, но namespace объявлен как Content.Server._Sunrise.Silicons.Borgs.Components. Для _Lust-специфичного контента ожидается неймспейс вида Content.Server._Lust.Borgs (или аналогичный).

♻️ Предлагаемое исправление
-namespace Content.Server._Sunrise.Silicons.Borgs.Components;
+namespace Content.Server._Lust.Borgs;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs` at line 11, The file's
declared namespace (Content.Server._Sunrise.Silicons.Borgs.Components) does not
match its repository path (Content.Server/_Lust/Borgs); update the namespace
declaration to the correct Lust-specific namespace (e.g.,
Content.Server._Lust.Borgs or Content.Server._Lust.Borgs.Components) so it
matches the folder structure and any types in this file such as
BorgModuleInnateSystem; ensure any using/imports or references to this class are
adjusted if necessary.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs`:
- Line 159: The code uses MetaData(item).EntityPrototype!.ID with a
null-forgiving operator which can still throw a NullReferenceException; change
the call site in the _actions.SetIcon flow to null-check
MetaData(item).EntityPrototype before using its ID (the symbols to edit are
MetaData(item).EntityPrototype, _actions.SetIcon, and
SpriteSpecifier.EntityPrototype), and if EntityPrototype is null, handle it
gracefully (e.g., log a warning/error and skip setting the sprite or use a safe
fallback SpriteSpecifier) instead of dereferencing with !.
- Around line 38-39: Обработчики OnInnateUseItem и OnInnateInteractionItem
подписаны на сущности с BorgModuleInnateComponent, но действия регистрируются на
шасси через _actions.AddAction(chassis, action, module.Owner), поэтому события
поднимаются на шасси и никогда не доходят до модуля; исправьте это либо
переставив подписку на шасси и при получении события вручную ретранслируя его на
соответствующий модуль (найдите место подписки SubscribeLocalEvent<...> и
переключите цель на шасси, делая lookup по module.Owner), либо оберните события
в BorgModuleRelayedEvent<T> по образцу SharedBorgSystem.Relay.cs и подпишитесь
на релеи́рованные события для BorgModuleInnateComponent.

---

Duplicate comments:
In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs`:
- Around line 61-72: In OnUninstalled, after calling
_actions.RemoveAction(args.ChassisEnt, action) you must also queue deletion of
the action entity to avoid orphaned action entities left in the module
container; iterate module.Comp.Actions and call the appropriate deletion method
(QueueDel) for each action entity (these were previously added via
_actionContainer.AddAction(module.Owner, action)) before/after clearing
module.Comp.Actions, and keep the existing _containers.CleanContainer call for
InnateItemsContainerId; ensure you reference OnUninstalled,
_actions.RemoveAction, _actionContainer.AddAction, _containers.CleanContainer,
module.Comp.Actions, module.Owner, action and use QueueDel for deletion.

---

Nitpick comments:
In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs`:
- Around line 47-55: The code calls
_containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId,
containerManager) but ignores its return value and then calls
_containers.TryGetContainer(...) which is unnecessary and makes the subsequent
return unreachable; instead capture the container returned by EnsureContainer
(assign to a variable, e.g. var container =
_containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId,
containerManager)), remove the TryGetContainer branch and unreachable return,
and pass that container directly to AddItems(args.ChassisEnt, module,
container); keep a null check only if EnsureContainer can return null (otherwise
omit).
- Line 11: The file's declared namespace
(Content.Server._Sunrise.Silicons.Borgs.Components) does not match its
repository path (Content.Server/_Lust/Borgs); update the namespace declaration
to the correct Lust-specific namespace (e.g., Content.Server._Lust.Borgs or
Content.Server._Lust.Borgs.Components) so it matches the folder structure and
any types in this file such as BorgModuleInnateSystem; ensure any using/imports
or references to this class are adjusted if necessary.

In `@Content.Server/_Sunrise/InteractionsPanel/InteractionsPanel.Interactions.cs`:
- Around line 579-583: Swap the guard checks so
HasComp<InteractionsComponent>(args.User) runs before
TryComp<UserInterfaceComponent>(args.User, out var interfaceComponent);
specifically, move the HasComp<InteractionsComponent> check above the
TryComp<UserInterfaceComponent> call to reject users without an
InteractionsComponent early and avoid the more expensive TryComp operation on
those users (keep returning immediately in both guards and preserve the same
variables/names: args.User, InteractionsComponent, UserInterfaceComponent,
interfaceComponent).

In `@Resources/Prototypes/_Lust/Entities/ERP/Toys/toys.yml`:
- Line 226: The YAML contains inconsistent parent notation: replace the array
form parent: [ERPToy] with the scalar form parent: ERPToy wherever the
single-parent array is used (i.e., change every occurrence of parent: [ERPToy]
to parent: ERPToy) so it matches the existing scalar usage; search for the key
"parent" with the value "[ERPToy]" and update those entries to "parent: ERPToy"
to keep notation consistent.

{
var actionEnt = Spawn(actionProto);
// Подгружаем спрайт для экшена из прото предмета
_actions.SetIcon(actionEnt, new SpriteSpecifier.EntityPrototype(MetaData(item).EntityPrototype!.ID));
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Оператор ! подавляет предупреждение, но не защищает от NRE.

MetaData(item).EntityPrototype!.ID — если EntityPrototype окажется null (например, при горячей перезагрузке прототипа или некорректном YAML), будет выброшен NullReferenceException. Предпочтительнее явная проверка:

🛡️ Предлагаемое исправление
-        _actions.SetIcon(actionEnt, new SpriteSpecifier.EntityPrototype(MetaData(item).EntityPrototype!.ID));
+        var proto = MetaData(item).EntityPrototype;
+        if (proto != null)
+            _actions.SetIcon(actionEnt, new SpriteSpecifier.EntityPrototype(proto.ID));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_actions.SetIcon(actionEnt, new SpriteSpecifier.EntityPrototype(MetaData(item).EntityPrototype!.ID));
var proto = MetaData(item).EntityPrototype;
if (proto != null)
_actions.SetIcon(actionEnt, new SpriteSpecifier.EntityPrototype(proto.ID));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs` at line 159, The code
uses MetaData(item).EntityPrototype!.ID with a null-forgiving operator which can
still throw a NullReferenceException; change the call site in the
_actions.SetIcon flow to null-check MetaData(item).EntityPrototype before using
its ID (the symbols to edit are MetaData(item).EntityPrototype,
_actions.SetIcon, and SpriteSpecifier.EntityPrototype), and if EntityPrototype
is null, handle it gracefully (e.g., log a warning/error and skip setting the
sprite or use a safe fallback SpriteSpecifier) instead of dereferencing with !.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут надо думать - система предполагает, что все предметы созданы по прототипу как-никак. И в самой системе так и есть.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@crestoedge, понимаю вашу точку зрения. Действительно, в архитектуре системы все предметы создаются через Spawn(itemProto) с валидным прототипом, и при нормальной работе EntityPrototype всегда будет заполнен.

Использование ! здесь оправдано, если вы уверены в инвариантах системы. Единственный сценарий проблемы — это горячая перезагрузка прототипов или критическая ошибка в данных, но такие случаи обычно приводят к более глобальным проблемам.

Оставляйте как есть, если считаете, что это соответствует архитектурным гарантиям системы. 👍


🧠 Learnings used
Learnt from: Orvex07
Repo: space-sunrise/lust-station PR: 442
File: Resources/Prototypes/_Lust/CP/Weapons/hl2_weapons.yml:56-105
Timestamp: 2025-12-31T16:02:40.555Z
Learning: В проекте space-sunrise/lust-station при анализе PR с контентом в директории _Lust/CP необходимо проверять существование прототипов не только в файлах PR, но и в upstream директории _Sunrise, так как _Lust может использовать прототипы оружия, магазинов и других предметов из _Sunrise (например, MagazineMP7 определён в Resources/Prototypes/_Sunrise/Entities/Objects/Weapons/Guns/Ammunition/Magazines/pistol.yml).

Learnt from: Kendrick15
Repo: space-sunrise/lust-station PR: 301
File: Resources/Locale/ru-RU/_strings/_lust/flavors/flavor-profiles.ftl:1-1
Timestamp: 2025-07-08T21:33:23.476Z
Learning: Проект lust-station является взрослым контентом с ERP (Erotic Role Play) функциональностью, где активно используется ненормативная лексика в локализациях, включая акценты персонажей, комментарии разработчиков и игровой контент. Стиль локализации соответствует взрослой тематике проекта.

Learnt from: Esco-dev
Repo: space-sunrise/lust-station PR: 427
File: Resources/Prototypes/_Sunrise/Roles/Jobs/Command/nanotrasen_representative.yml:7-7
Timestamp: 2025-12-12T08:52:50.213Z
Learning: В проекте space-sunrise/lust-station используется комментарий "# Lust Edit" для маркировки изменений в файлах относительно upstream проекта sunrise-station. Эти комментарии являются частью системы документирования fork-специфичных изменений и не должны удаляться.

Learnt from: Esco-dev
Repo: space-sunrise/lust-station PR: 427
File: Resources/Prototypes/_Sunrise/Roles/Jobs/Command/nanotrasen_representative.yml:7-7
Timestamp: 2025-12-12T08:52:35.387Z
Learning: В проекте space-sunrise/lust-station используется комментарий "#Lust Edit" для маркировки изменений в файлах, специфичных для форка lust-station. Эти комментарии являются частью системы документирования изменений относительно upstream проекта sunrise-station и не должны удаляться.

Learnt from: darneya
Repo: space-sunrise/lust-station PR: 425
File: Resources/Prototypes/_Lust/CP/Clothing/jumpsuits.yml:197-208
Timestamp: 2025-12-27T09:48:52.949Z
Learning: В проекте space-sunrise/lust-station при добавлении контента Half-Life 2 (HL2) по техническому заданию пользователя Wein описания предметов должны строго следовать предоставленному ТЗ, даже если они могут показаться семантически несоответствующими названию предмета (например, ClothingUniformJumpsuitCPRefugee с описанием помощника на поле боя).

@crestoedge
Copy link
Contributor Author

лучше дать статус всем, а ещё лучше - читать ебучий статус в профиле и присваивать его боргу

@Kideo000
Copy link

лучше дать статус всем, а ещё лучше - читать ебучий статус в профиле и присваивать его боргу

Хмм может тогда получится привязать еще и описание?

@crestoedge
Copy link
Contributor Author

Не думаю - тогда надо отдельное описание для борга, что звучит избыточно (и вне темы ПРа это точно)

@crestoedge
Copy link
Contributor Author

Мегаультранасрал коммитами, но теперь всё точно пашет и по коду адекватно. Есть идейка для одного гиммика, сейчас буду делать его.
На счет статуса и лодаута - я посмотрю что можно сделать, надеюсь там не придётся долго страдать.

@Scream-Ae
Copy link

Мегаультранасрал коммитами, но теперь всё точно пашет и по коду адекватно. Есть идейка для одного гиммика, сейчас буду делать его. На счет статуса и лодаута - я посмотрю что можно сделать, надеюсь там не придётся долго страдать.

сделать бы ещё какой то вариант для установления "мужской" панели ну и/или футы

@Kideo000
Copy link

Мегаультранасрал коммитами, но теперь всё точно пашет и по коду адекватно. Есть идейка для одного гиммика, сейчас буду делать его. На счет статуса и лодаута - я посмотрю что можно сделать, надеюсь там не придётся долго страдать.

сделать бы ещё какой то вариант для установления "мужской" панели ну и/или футы

Увы нассколько я знаю не получится да и все юниты женского телосложения.. так что будет не по РП а так игрушки в помощь

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
Content.Server/_Lust/Borgs/BorgModuleInnateComponent.cs (1)

15-22: Допускать null в List<EntProtoId?> не имеет смысла.

Нулевые записи пропускаются в системе через явные проверки if (itemProto is null) continue. Упрощение до List<EntProtoId> (без ?) устранит возможность случайного добавления null в YAML-конфигурации.

♻️ Предлагаемое изменение
-    public List<EntProtoId?> UseItems = new();
+    public List<EntProtoId> UseItems = new();
 
-    public List<EntProtoId?> InteractionItems = new();
+    public List<EntProtoId> InteractionItems = new();

И соответствующее упрощение в BorgModuleInnateSystem.cs:

-        foreach (var itemProto in module.Comp.UseItems)
-        {
-            if (itemProto is null)
-                continue;
-            AddUseItem(itemProto.Value, chassis, module, container);
-        }
+        foreach (var itemProto in module.Comp.UseItems)
+            AddUseItem(itemProto, chassis, module, container);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Server/_Lust/Borgs/BorgModuleInnateComponent.cs` around lines 15 -
22, The fields UseItems and InteractionItems in BorgModuleInnateComponent are
declared as List<EntProtoId?> allowing null entries which are later explicitly
skipped; change their types to List<EntProtoId> (remove the nullable) to prevent
nulls from being added via YAML and update any code in BorgModuleInnateSystem
that iterates or assigns these lists to stop handling nullable values (remove
null-check branches and adjust variable types/signatures to EntProtoId),
ensuring serialization attributes ([DataField]) remain intact.
Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs (1)

45-56: InnateComponents не отслеживает, какие компоненты фактически добавлены этим модулем.

EntityManager.AddComponents (строка 50) добавляет компоненты без проверки наличия, а EntityManager.RemoveComponents (строка 71) при деинсталляции удаляет весь реестр. Если будущий модуль тоже объявит пересекающийся компонент в InnateComponents, деинсталляция первого сломает второй.

Рекомендуется добавить поле ComponentRegistry InstalledComponents в BorgModuleInnateComponent и при установке записывать только те компоненты, которых ещё не было, а при удалении — только их. Это обсуждалось в предыдущих итерациях ревью и пока не реализовано.

Also applies to: 71-71

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs` around lines 45 - 56, В
компонент BorgModuleInnateComponent добавить поле ComponentRegistry
InstalledComponents и изменить логику в OnInstalled (метод OnInstalled и
соответствующий обработчик деинсталляции) так: при вызове
EntityManager.AddComponents проверять для каждого компонента из
InnateComponents, существует ли он уже на args.ChassisEnt; только отсутствующие
компоненты добавлять и регистрировать их в InstalledComponents; при
деинсталляции использовать InstalledComponents как источник для
EntityManager.RemoveComponents, удаляя только те компоненты, которые были
реально добавлены этим модулем, и очищая/обнуляя запись в InstalledComponents
после удаления.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs`:
- Around line 61-72: В методе OnUninstalled (BorgModuleInnateSystem) необходимо
удалять сущности экшенов, а не только убирать их гранты: перед
module.Comp.Actions.Clear() вызовите QueueDel для каждой сущности action в
module.Comp.Actions (после/до _actions.RemoveAction(args.ChassisEnt, action) —
так, чтобы грант снят, затем сам entity помечен на удаление), затем очистите
список и продолжите удаление InnateItems/InnateComponents; это предотвратит
оставление старых экшенов в контейнере модуля при переустановке.

---

Nitpick comments:
In `@Content.Server/_Lust/Borgs/BorgModuleInnateComponent.cs`:
- Around line 15-22: The fields UseItems and InteractionItems in
BorgModuleInnateComponent are declared as List<EntProtoId?> allowing null
entries which are later explicitly skipped; change their types to
List<EntProtoId> (remove the nullable) to prevent nulls from being added via
YAML and update any code in BorgModuleInnateSystem that iterates or assigns
these lists to stop handling nullable values (remove null-check branches and
adjust variable types/signatures to EntProtoId), ensuring serialization
attributes ([DataField]) remain intact.

In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs`:
- Around line 45-56: В компонент BorgModuleInnateComponent добавить поле
ComponentRegistry InstalledComponents и изменить логику в OnInstalled (метод
OnInstalled и соответствующий обработчик деинсталляции) так: при вызове
EntityManager.AddComponents проверять для каждого компонента из
InnateComponents, существует ли он уже на args.ChassisEnt; только отсутствующие
компоненты добавлять и регистрировать их в InstalledComponents; при
деинсталляции использовать InstalledComponents как источник для
EntityManager.RemoveComponents, удаляя только те компоненты, которые были
реально добавлены этим модулем, и очищая/обнуляя запись в InstalledComponents
после удаления.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs (1)

47-53: Возвращаемое значение EnsureContainer игнорируется, а последующий TryGetContainer — недостижимый код.

EnsureContainer гарантирует существование контейнера и возвращает его. Результат выброшен, после чего TryGetContainer немедленно вызывается на том же контейнере — он всегда вернёт true, а ранний return на строке 53 недостижим. Вдобавок AddComponents вызывается до этой мёртвой проверки: если бы ранний return когда-либо сработал, компоненты уже были бы добавлены без предметов.

♻️ Предлагаемое исправление
-        var containerManager = EnsureComp<ContainerManagerComponent>(args.ChassisEnt);
-        _containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId, containerManager);
-
-        EntityManager.AddComponents(args.ChassisEnt, module.Comp.InnateComponents);
-
-        if (!_containers.TryGetContainer(args.ChassisEnt, InnateItemsContainerId, out var container))
-            return;
-
-        AddItems(args.ChassisEnt, module, container);
+        var containerManager = EnsureComp<ContainerManagerComponent>(args.ChassisEnt);
+        var container = _containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId, containerManager);
+
+        EntityManager.AddComponents(args.ChassisEnt, module.Comp.InnateComponents);
+        AddItems(args.ChassisEnt, module, container);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs` around lines 47 - 53,
Метод _containers.EnsureContainer возвращает и гарантирует контейнер, поэтому
текущий вызов игнорирует результат, делает последующий
_containers.TryGetContainer ненужным и делает ранний return недостижимым; также
EntityManager.AddComponents вызывается до проверки контейнера. Исправьте так:
присвойте результат EnsureContainer (например var container =
_containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId,
containerManager)) и удалите ненужный TryGetContainer/return либо, если вы
хотите защитную проверку, используйте TryGetContainer вместо EnsureContainer; в
любом случае переместите EntityManager.AddComponents так, чтобы компоненты
добавлялись после успешного получения/создания контейнера (ссылки:
EnsureContainer, TryGetContainer, EntityManager.AddComponents, _containers).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs`:
- Around line 38-39: The event handlers
SubscribeLocalEvent<BorgModuleInnateComponent, ModuleInnateUseItem> and
SubscribeLocalEvent<BorgModuleInnateComponent, ModuleInnateInteractionItem> are
registered on the module entity but the actions are raised on the chassis via
_actions.AddAction(chassis, action, module.Owner), so
OnInnateUseItem/OnInnateInteractionItem never fire; fix by changing the routing
to relay the directed events from the chassis to the module: either subscribe to
ModuleInnateUseItem/ModuleInnateInteractionItem on the chassis (i.e. listen for
events on the performer entity) and in those handlers forward/raise the
corresponding event on module.Owner, or implement the BorgModuleRelayedEvent<T>
pattern (see SharedBorgSystem.Relay.cs) so the chassis-raised events are
automatically relayed to the BorgModuleInnateComponent and will invoke
OnInnateUseItem and OnInnateInteractionItem.

---

Nitpick comments:
In `@Content.Server/_Lust/Borgs/BorgModuleInnateSystem.cs`:
- Around line 47-53: Метод _containers.EnsureContainer возвращает и гарантирует
контейнер, поэтому текущий вызов игнорирует результат, делает последующий
_containers.TryGetContainer ненужным и делает ранний return недостижимым; также
EntityManager.AddComponents вызывается до проверки контейнера. Исправьте так:
присвойте результат EnsureContainer (например var container =
_containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId,
containerManager)) и удалите ненужный TryGetContainer/return либо, если вы
хотите защитную проверку, используйте TryGetContainer вместо EnsureContainer; в
любом случае переместите EntityManager.AddComponents так, чтобы компоненты
добавлялись после успешного получения/создания контейнера (ссылки:
EnsureContainer, TryGetContainer, EntityManager.AddComponents, _containers).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Resources/Textures/Objects/Specific/Medical/hypospray.rsi/meta.json (1)

4-4: ⚠️ Potential issue | 🟡 Minor

Добавьте атрибуцию для спрайта borghypolustful в поле "copyright"

Лицензия CC-BY-SA-3.0 требует указания автора. Спрайт borghypolustful не упомянут в текущей строке copyright, тогда как все остальные спрайты имеют явную атрибуцию.

✏️ Предлагаемое исправление
-    "copyright": "Taken from vgstation at commit https://github.com/vgstation-coders/vgstation13/commit/1cdfb0230cc96d0ba751fa002d04f8aa2f25ad7d, modified with fill sprites by SlamBamActionman (github), borghypo  fill sprites by SirWarock (Github)",
+    "copyright": "Taken from vgstation at commit https://github.com/vgstation-coders/vgstation13/commit/1cdfb0230cc96d0ba751fa002d04f8aa2f25ad7d, modified with fill sprites by SlamBamActionman (github), borghypo fill sprites by SirWarock (Github), borghypolustful sprite by crestoedge (Github)",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Resources/Textures/Objects/Specific/Medical/hypospray.rsi/meta.json` at line
4, The copyright string in meta.json is missing attribution for the sprite
"borghypolustful"; update the "copyright" field in
Resources/Textures/Objects/Specific/Medical/hypospray.rsi/meta.json to
explicitly credit the author of "borghypolustful" (e.g., add "borghypolustful by
<author>" or the correct author handle) alongside the existing attributions so
the CC-BY-SA-3.0 requirement is satisfied.
🧹 Nitpick comments (3)
Resources/Prototypes/_Lust/Entities/Objects/Specific/Robotics/borg_tools.yml (3)

17-18: Захардкоженные name/description дублируют FTL-записи

В SS14 FTL-файлы имеют приоритет над значениями из YAML, поэтому поля name и description в прототипе фактически игнорируются при наличии соответствующих FTL-ключей. Можно убрать их из YAML.

♻️ Предлагаемое исправление
 - type: entity
   parent: HypoBorgStandard
   id: HypoBorgLustful
-  name: lustful borg hypospray
-  description: A cyborg hypospray that produces various excitatory chemicals to inject into people.
   categories: [ HideSpawnMenu ]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Resources/Prototypes/_Lust/Entities/Objects/Specific/Robotics/borg_tools.yml`
around lines 17 - 18, В данном прототипе удалите захардкоженные поля name и
description для записи прототипа "lustful borg hypospray" — эти ключи дублируют
FTL-локализации и игнорируются движком; откройте запись прототипа и удалите
строки с name: и description: (либо закомментируйте их), оставив только
остальные поля прототипа.

1-2: Удалите отладочные комментарии перед мержем

Неформальные комментарии разработчика не подходят для production-кода.

✏️ Предлагаемое исправление
-# Либо новый файл для этого, либо прописать здесь
-# угадайте что я выбрал
 - type: injectorMode
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Resources/Prototypes/_Lust/Entities/Objects/Specific/Robotics/borg_tools.yml`
around lines 1 - 2, Remove the informal/debug comments that start with "# Либо
новый файл для этого, либо прописать здесь" and "# угадайте что я выбрал" from
the borg_tools.yml stub; replace them with a concise YAML-friendly description
or proper metadata (e.g., a "description:" field) if necessary so no developer
side-notes remain in production files.

3-12: MicroHyposprayMode — мёртвый код: MicroHyposprayInjectMode не наследует от него

MicroHyposprayMode объявлен как abstract: true и задаёт transferAmounts: [1], однако MicroHyposprayInjectMode указывает родителей как [BaseHyposprayMode, BaseInjectMode], а не [MicroHyposprayMode, BaseInjectMode]. В результате:

  • вместо transferAmounts: [1] из MicroHyposprayMode наследуется transferAmounts: [5] из BaseHyposprayMode;
  • MicroHyposprayMode нигде не используется как родитель и остаётся неиспользованным.

Исправьте цепь наследования:

♻️ Предлагаемое исправление
 - type: injectorMode
-  parent: [ BaseHyposprayMode, BaseInjectMode ]
+  parent: [ MicroHyposprayMode, BaseInjectMode ]
   id: MicroHyposprayInjectMode
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Resources/Prototypes/_Lust/Entities/Objects/Specific/Robotics/borg_tools.yml`
around lines 3 - 12, MicroHyposprayMode is declared abstract and sets
transferAmounts: [1] but is never used because MicroHyposprayInjectMode inherits
from BaseHyposprayMode instead of MicroHyposprayMode; update the parent list of
MicroHyposprayInjectMode to inherit from MicroHyposprayMode (and BaseInjectMode)
so it receives transferAmounts: [1] from MicroHyposprayMode; verify references
to MicroHyposprayMode, MicroHyposprayInjectMode, BaseHyposprayMode,
BaseInjectMode and ensure no other child still points to BaseHyposprayMode if
they should use the micro variant.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@Resources/Locale/ru-RU/_prototypes/_lust/entities/objects/specific/robotics/borg_tools.ftl`:
- Line 1: Замените некорректную фразу в переводе для ключа ent-HypoBorgLustful:
вместо «гипоспрей киборга для похотей» используйте натуральную русскую
конструкцию с прилагательным, например «гипоспрей похотливого киборга» —
отредактируйте значение ent-HypoBorgLustful соответственно.

In
`@Resources/Prototypes/_Lust/Entities/Objects/Specific/Robotics/borg_modules.yml`:
- Around line 36-37: Запись HypoBorgLustful в списке hands пропущена вложенная
секция hand: с emptyRepresentative и whitelist; добавьте для записи
HypoBorgLustful блок hand: содержащий emptyRepresentative (тот же
ресурс/представление, что и у других записей в hands) и whitelist,
ограничивающий заменяемые предметы только допустимыми (например, тот же набор,
что у остальных BorgModuleInnate), чтобы слот корректно отображался пустым и
гипоспрей нельзя было заменить произвольным предметом.
- Around line 37-41: In BorgModuleInnateSystem.OnInstalled, don't add ErpStatus
unconditionally via EntityManager.AddComponents(args.ChassisEnt,
module.Comp.InnateComponents); instead, filter module.Comp.InnateComponents and
skip any ErpStatus component that would turn ERP on when the installing player's
profile has ERP disabled (check the player's profile ERP flag on args.Player or
similar), then call EntityManager.AddComponents with the filtered list so a
module cannot override a player's Erp: No setting.

---

Outside diff comments:
In `@Resources/Textures/Objects/Specific/Medical/hypospray.rsi/meta.json`:
- Line 4: The copyright string in meta.json is missing attribution for the
sprite "borghypolustful"; update the "copyright" field in
Resources/Textures/Objects/Specific/Medical/hypospray.rsi/meta.json to
explicitly credit the author of "borghypolustful" (e.g., add "borghypolustful by
<author>" or the correct author handle) alongside the existing attributions so
the CC-BY-SA-3.0 requirement is satisfied.

---

Nitpick comments:
In
`@Resources/Prototypes/_Lust/Entities/Objects/Specific/Robotics/borg_tools.yml`:
- Around line 17-18: В данном прототипе удалите захардкоженные поля name и
description для записи прототипа "lustful borg hypospray" — эти ключи дублируют
FTL-локализации и игнорируются движком; откройте запись прототипа и удалите
строки с name: и description: (либо закомментируйте их), оставив только
остальные поля прототипа.
- Around line 1-2: Remove the informal/debug comments that start with "# Либо
новый файл для этого, либо прописать здесь" and "# угадайте что я выбрал" from
the borg_tools.yml stub; replace them with a concise YAML-friendly description
or proper metadata (e.g., a "description:" field) if necessary so no developer
side-notes remain in production files.
- Around line 3-12: MicroHyposprayMode is declared abstract and sets
transferAmounts: [1] but is never used because MicroHyposprayInjectMode inherits
from BaseHyposprayMode instead of MicroHyposprayMode; update the parent list of
MicroHyposprayInjectMode to inherit from MicroHyposprayMode (and BaseInjectMode)
so it receives transferAmounts: [1] from MicroHyposprayMode; verify references
to MicroHyposprayMode, MicroHyposprayInjectMode, BaseHyposprayMode,
BaseInjectMode and ensure no other child still points to BaseHyposprayMode if
they should use the micro variant.

@@ -0,0 +1,2 @@
ent-HypoBorgLustful = гипоспрей киборга для похотей
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Некорректная формулировка названия

«гипоспрей киборга для похотей» — неестественное словосочетание в русском языке; «для похотей» не является устойчивым переводом прилагательного lustful. Правильнее использовать прилагательное «похотливый».

✏️ Предлагаемое исправление
-ent-HypoBorgLustful = гипоспрей киборга для похотей
+ent-HypoBorgLustful = похотливый гипоспрей киборга
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ent-HypoBorgLustful = гипоспрей киборга для похотей
ent-HypoBorgLustful = похотливый гипоспрей киборга
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Resources/Locale/ru-RU/_prototypes/_lust/entities/objects/specific/robotics/borg_tools.ftl`
at line 1, Замените некорректную фразу в переводе для ключа ent-HypoBorgLustful:
вместо «гипоспрей киборга для похотей» используйте натуральную русскую
конструкцию с прилагательным, например «гипоспрей похотливого киборга» —
отредактируйте значение ent-HypoBorgLustful соответственно.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можешь придумать другое название получше? Я без понятия как его лучше назвать.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@crestoedge, вот несколько вариантов названия, которые звучат естественнее:

Рекомендую:

  1. возбуждающий гипоспрей киборга — согласуется с описанием, где используется "возбуждающие химикаты", звучит естественно и понятно передаёт назначение

Альтернативы:
2. похотливый гипоспрей киборга — прямой перевод "lustful", более игривый тон
3. сладострастный гипоспрей киборга — литературный вариант, звучит изысканнее
4. гипоспрей страсти киборга — нейтральнее, но понятно

Я бы выбрал первый вариант (возбуждающий гипоспрей киборга), потому что:

  • Грамматически правильный
  • Использует ту же терминологию, что и в описании
  • Чётко передаёт функцию предмета
  • Звучит естественно для носителя русского языка

Какой вариант больше подходит?


🧠 Learnings used
Learnt from: darneya
Repo: space-sunrise/lust-station PR: 425
File: Resources/Prototypes/_Lust/CP/Clothing/jumpsuits.yml:197-208
Timestamp: 2025-12-27T09:48:52.949Z
Learning: В проекте space-sunrise/lust-station при добавлении контента Half-Life 2 (HL2) по техническому заданию пользователя Wein описания предметов должны строго следовать предоставленному ТЗ, даже если они могут показаться семантически несоответствующими названию предмета (например, ClothingUniformJumpsuitCPRefugee с описанием помощника на поле боя).

Learnt from: APA64IK
Repo: space-sunrise/lust-station PR: 471
File: Resources/Locale/ru-RU/_prototypes/_lust/entities/erp/toys/toys.ftl:27-30
Timestamp: 2026-02-13T14:15:17.129Z
Learning: В проекте space-sunrise/lust-station для цветовых вариантов верёвок шибари (ERPShibariRopeRed, ERPShibariRopeWhite) в файлах локализации Resources/Locale/*/entities/erp/toys/toys.ftl используются прямые ссылки на родительский объект ERPShibariRope для имени и описания (формат: `ent-ERPShibariRopeRed = { ent-ERPShibariRope }`), чтобы избежать дублирования кода, даже если это приводит к идентичным отображаемым именам. Это явное архитектурное решение maintainer'а Orvex07.

Learnt from: CR
Repo: space-sunrise/lust-station PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-01T18:35:30.075Z
Learning: Write changelog messages in Russian for consistency with existing entries

Learnt from: Kendrick15
Repo: space-sunrise/lust-station PR: 301
File: Resources/Locale/ru-RU/_strings/_lust/flavors/flavor-profiles.ftl:1-1
Timestamp: 2025-07-08T21:33:23.476Z
Learning: Проект lust-station является взрослым контентом с ERP (Erotic Role Play) функциональностью, где активно используется ненормативная лексика в локализациях, включая акценты персонажей, комментарии разработчиков и игровой контент. Стиль локализации соответствует взрослой тематике проекта.

@crestoedge
Copy link
Contributor Author

Лодауты будут

@crestoedge
Copy link
Contributor Author

Или не будут. Я до сих пор не могу сделать так, чтобы оно применило гребанный лоадаут.

@crestoedge crestoedge marked this pull request as draft February 21, 2026 21:31
@crestoedge
Copy link
Contributor Author

Конвертирую в драфт - такое количество изменений систем во-первых вряд-ли приймут, во-вторых - ПР со всеми изменениями систем будет открыт на Санрайз.

@crestoedge
Copy link
Contributor Author

crestoedge commented Feb 21, 2026

это победа, товарищи
ПР закончен, нужны только багфиксы (и порт на Санрайз)

@crestoedge crestoedge force-pushed the service-borg-lewd-module branch from 7ce1bad to 45e3c12 Compare February 22, 2026 08:10
@koshaciyxvii
Copy link

Пиздец вы тут совсем ебобо на голову

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants